package com.itcast.springboot3x.thread;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.*;

/**
 * 访问自定义Endpoint：
 * http://ip:8080/actuator/thread-pool，就可以看到如下数据。我们可以把这个Endpoint配置到Prometheus中，Prometheus会定时抓取这些指标存储并展示，从而完成线程池的整体监控
 * 用来实现线程池的管理和初始化，实现线程池的统一管理，初始化的逻辑是根据application.properties中配置的属性来实现的
 * 从配置类中获得线程池的基本配置。
 * 根据配置信息构建ThreadPoolExecutorForMonitor实例。
 * 把实例信息保存到集合中
 * @author zhangtian105
 * @date 2023/5/18
 * @apiNote
 */
@Component
public class ThreadPoolForMonitorManager {
    @Autowired
    ThreadPoolConfigurationProperties poolConfigurationProperties;
    private final ConcurrentMap<String, ThreadPoolExecutorForMonitor> threadPoolMap = new ConcurrentHashMap<>();

    /**
     * 初始化创建线程池
     * 可以自己实现创建线程池
     */
    @PostConstruct
    public void init(){
        poolConfigurationProperties.getExecutors().forEach(threadPoolProperties -> {
            if(!threadPoolMap.containsKey(threadPoolProperties.getPoolName())){
                ThreadPoolExecutorForMonitor executorForMonitor = new ThreadPoolExecutorForMonitor(
                        threadPoolProperties.getCorePoolSize(),
                        threadPoolProperties.getMaxmumPoolSize(),
                        threadPoolProperties.getKeepAliveTime(),
                        threadPoolProperties.getUnit(),
                        new LinkedBlockingQueue<>(threadPoolProperties.getQueueCapacity()),
                        threadPoolProperties.getPoolName(),
                        new ThreadPoolExecutor.CallerRunsPolicy());

                threadPoolMap.put(threadPoolProperties.getPoolName(), executorForMonitor);
            }
        });
    }

    public ThreadPoolExecutorForMonitor getThreadPoolExecutor(String poolName){
        ThreadPoolExecutorForMonitor threadPoolExecutorForMonitor = threadPoolMap.get(poolName);

        if(threadPoolExecutorForMonitor == null){
            throw new RuntimeException("找不到名字为"+poolName+"的线程池");
        }

        return threadPoolExecutorForMonitor;
    }

    public ConcurrentMap<String,ThreadPoolExecutorForMonitor> getThreadPoolMap(){
        return this.threadPoolMap;
    }
}
